﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;
using System.Windows.Markup;
using System.Linq;

namespace Slex.Lib.Interactions
{
    /// <summary>
    /// An action to invoke an ICommand in the view model
    /// </summary>
    [ContentProperty("Parameters")]     
    public class InvokeCommandAction
        : TargettedTriggerAction
    {
            public string CommandName
            {
                get { return (string)GetValue(CommandNameProperty); }
                set { SetValue(CommandNameProperty, value); }
            }

            // Using a DependencyProperty as the backing store for CommandName.  This enables animation, styling, binding, etc...
            public static readonly DependencyProperty CommandNameProperty =
                DependencyProperty.Register("CommandName", typeof(string), typeof(InvokeCommandAction), new PropertyMetadata(string.Empty));


            /// <summary>
            /// A set of parameters this method will take
            /// </summary>
            public ActionParameters Parameters
            {
                get { return (ActionParameters)GetValue(MethodParametersProperty); }
                set { SetValue(MethodParametersProperty, value); }
            }

            // Using a DependencyProperty as the backing store for Conditions.  This enables animation, styling, binding, etc...
            public static readonly DependencyProperty MethodParametersProperty =
                DependencyProperty.Register("Parameters", typeof(ActionParameters), typeof(InvokeCommandAction), new PropertyMetadata(null));


           

            /// <summary>
            /// Invoke this command conditionally
            /// </summary>
            /// <param name="parameter"></param>
            internal override void InvokeConditional(object parameter)
            {

                if (Target != null)
                {
                    var prop = Target.GetType().GetProperty(CommandName);
                    if (prop == null) throw new InvalidOperationException("Unable to find Command " + CommandName);
                    var cmd = prop.GetValue(Target, null) as ICommand;
                    if (cmd == null) throw new InvalidOperationException("The Command " + CommandName + " is not an ICommand");

                    List<object> ps = new List<object>();
                    object cmdparams = null;

                    if (Parameters != null)
                    {
                        if (Parameters.Count > 1)
                        {
                            foreach (var p in Parameters)
                                ps.Add(p.PropertyValue);
                            cmdparams = ps.ToArray();
                        }
                        else if (Parameters.Count == 1)
                        {
                            cmdparams = Parameters[0].PropertyValue;
                        }

                    }

                    if (cmd.CanExecute(cmdparams))
                        cmd.Execute(cmdparams);

                }
            }

            internal override void InternalInitialize()
            {
                base.InternalInitialize();

                if (Parameters != null)
                {
                    Parameters.ToList().ForEach(p =>
                    { p.TriggerContext = TriggerContext; p.AssociatedObject = this.AssociatedObject; p.InternalInitialize(); });
                }
            }

    }
}
